﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Text.RegularExpressions;
using System.Collections;

namespace WinRos
{
    using Procurios.Public;

    class WinRos
    {
        private Socket connection;
        private IPAddress host;
        private IPEndPoint hostep;

        public WinRos(string theAddress)
        {
            if (theAddress == "")
            {
                //my netbook
                host = IPAddress.Parse("192.168.1.66");
                hostep = new IPEndPoint(host, 9090);
                connection = new Socket(AddressFamily.InterNetwork,
                                                   SocketType.Stream, ProtocolType.Tcp);
                connection.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }
            else
            {
                host = IPAddress.Parse(theAddress);
                hostep = new IPEndPoint(host, 9090);
                connection = new Socket(AddressFamily.InterNetwork,
                                                   SocketType.Stream, ProtocolType.Tcp);
                connection.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }

            try
            {
                Console.WriteLine("Im about to try to connect");
                if (connection.Connected)
                {
                    connection.Close();
                }
                connection.Connect(hostep);
                Console.WriteLine("I HAVE CONNECTED");
            }
            catch (SocketException e)
            {
                Console.WriteLine("Problem connecting to host");
                Console.WriteLine(e.ToString());
                connection.Close();
                return;
            }

            //performs the handshake
            this.handShake();
        }

        private void handShake()
        {
            String handshake = "raw\r\n\r\n";

            int i = this.connection.Send(Encoding.UTF8.GetBytes(handshake));
            Console.WriteLine("The handshake has been sent and it is {0} bytes ", i);
        }

        public void publish(string message)
        {

            int i = 0;
            try
            {

                i += this.connection.Send(new byte[] { 0 });
                i += this.connection.Send(Encoding.UTF8.GetBytes(message));
                i += this.connection.Send(new byte[] { 255 });
            }
            catch (SocketException e)
            {
                Console.WriteLine("{0} Error code: {1}.", e.Message, e.ErrorCode);
            }

            Console.WriteLine("The message has been sent and it is {0} bytes ", i);
        }

        public Hashtable receive()
        {
            /*
            int i = 0;
            byte[] bytes = new byte[1000000];
            try
            {
                i = this.connection.Receive(bytes);
                Console.WriteLine("This is the message that was received and it is {0} bytes ", i);
                //Console.WriteLine(Encoding.UTF8.GetString(bytes));

                //return Encoding.UTF8.GetString(bytes);
            }
            catch (SocketException e)
            {
                Console.WriteLine("{0} Error code: {1}.", e.Message, e.ErrorCode);
                //return (e.ErrorCode);
            }
            return Encoding.UTF8.GetString(bytes);
             */
            bool reachedEnd = false;
            int i = 0;
            int k = 0;
            ArrayList n = new ArrayList();
            byte[] end = new byte[] { 255 };

            while (reachedEnd == false)
            {
                byte[] buffer = new byte[1];
                i = this.connection.Receive(buffer, 0, 1, SocketFlags.None);

                if (byteArraysEqual(buffer,end))
                {
                    //you have reached the end of the message so get out
                    reachedEnd = true;
                }
                if (byteArrayEqualZero(buffer))
                {
                    //do nothing you dont want the zero
                }
                else
                {
                    //you have not reached the end keep reading
                    n.Add(Convert.ToByte(buffer[0]));
                    k++;
                }
            }
            byte[] read = (byte []) n.ToArray(typeof(byte));
            String final = Encoding.UTF8.GetString(read);


            return this.messageHandler(final);

        }

        public Hashtable messageHandler(string message)
        {
            Hashtable o = (Hashtable)JSON.JsonDecode(message);

            foreach(string key in o.Keys)
            {
                Console.WriteLine(String.Format("{0}: {1}", key, o[key]));

            }

            return o;
        }

        public void disconnect()
        {
            this.connection.Disconnect(true);
        }

        public bool isBlocking()
        {
            return this.connection.Blocking;
        }

        //returns zero if there is no data available
        public int isAvailable()
        {
            return this.connection.Available;
        }

        private bool byteArraysEqual(byte[] b1, byte[] b2)
        {
            if (b1 == b2) return true;
            if (b1 == null || b2 == null) return false;
            if (b1.Length != b2.Length) return false;
            for (int i = 0; i < b1.Length; i++)
            {
                if (b1[i] != b2[i]) return false;
            }
            return true;
        }

        private bool byteArrayEqualZero(byte[] b1)
        {
            byte[] zero = new byte[]{0};

            for (int i = 0; i < b1.Length; i++)
            {
                if (b1[i] != zero[i]) return false;
            }

            return true;
        }
    }
}
